
export default G6 => {
    G6.registerBehavior('drag-node', {
        getDefaultCfg() {
            return {
                sourceAnchorIndex: 0, // 锚点index
                dragTarget: 'node', // 记录当前拖拽的节点，可能是node也可能是锚点
                dragStartNode: {}, // 当前拖拽节点的配置数据
                distance: [] // 当前鼠标点击位置，距离节点中心位置的距离
            }
        },
        getEvents() {
            return {
                'node:mousedown': 'onNodeMousedown',
                'node:mouseup': 'onNodeMouseup',
                'node:dragstart': 'onNodeDragstart',
                'node:drag': 'onNodeDrag',
                'node:dragend': 'onNodeDragend',
                'node:drop': 'onNodeDrop'
            }
        }, // 鼠标按下，锚点显示光圈
        onNodeMousedown(e) {
            const graph = this.graph;
            const target = e.target; // Circle
            const item = e.item; // Node
            const isAnchor = target.get('isAnchor'); // 从cfg上取属性
            // 按下的是锚点，显示光圈
            if (isAnchor) {
                this.dragTarget = 'anchor';
                this.dragStartNode = {
                    ...item._cfg,
                    anchorIndex: target.get('index')
                }
                const nodes = graph.findAll('node', node => node);
                nodes.forEach(node => {
                    // 更改锚点激活状态
                    // graph.setItemState(node, 'anchorActive', true);
                    node.setState('anchorActive', true);
                    node.setState('anchorShow', true);
                });
            }
            graph.emit('on-node-mousedown', e);
        }, // 鼠标抬起，锚点还原
        onNodeMouseup(e) {
            const graph = this.graph;
            const target = e.target;
            const isAnchor = target.get('isAnchor');
            if (isAnchor) {
                const nodes = graph.findAll('node', node => node);
                nodes.forEach(node => {
                    // 更改锚点激活状态
                    node.clearStates('anchorActive');
                    node.setState('anchorShow', false);
                });
            }
        }, // 开始拖拽
        onNodeDragstart(e) {
            const graph = this.graph;
            const target = e.target;
            const node = e.item;
            const isAnchor = target.get('isAnchor');
            // 拖拽的是锚点，记录当前锚点索引
            if (isAnchor) {
                this.sourceAnchorIndex = target.get('index');
            } else {
                node.toFront();
                this.dragTarget = 'node';
                this._nodeOnDragStart(e, node);
            }
            graph.emit('on-node-dragstart', e);
        }, // 拖拽中
        onNodeDrag(e) {
            const node = e.item;
            if (this.dragTarget === 'node') {
                this._nodeOnDrag(e, node);
            }
            this.graph.emit('on-node-drag', e);
        }, // 拖拽结束
        onNodeDragend(e) {
            const graph = this.graph;
            const node = e.item;
            const group = node.get('group');
            // 1. 拖拽的是锚点，鼠标抬起，清除光圈
            if (this.dragTarget === 'anchor') {
                const nodes = graph.findAll('node', node => node);
                nodes.forEach(node => {
                    node.clearStates('anchorActive');
                })
            }
            // 拖拽的是节点，鼠标抬起，更新节点位置
            if (this.dragTarget === 'node') {
                this._nodeOnDragEnd(e, node);
            }
            graph.emit('on-node-dragend', e);
        }, // 拖拽结束：节点在画布中拖拽、锚点拖拽都会触发（我们只处理锚点拖拽，锚点拖拽结束添加边）
        onNodeDrop(e) {
            // e.item 当前拖拽节点 => Node  |  e.target 当前释放节点 => Rect/Circle
            const node = e.item;
            const target = e.target;
            // 如果拖拽的不是锚点，在同一个node节点连线，都阻止
            if (!target.get('isAnchor') || this.dragStartNode.id === node.get('nodeId')) return;
            const sourceNode = this.dragStartNode.group.get('item');
            const { singleEdge } = sourceNode.getModel();
            const targetAnchorIndex = target.get('index'); // 锚点索引
            const edges = sourceNode.getOutEdges(); // 获取sourceNode的所有边
            // 是否已经有连线
            // sourceAnchorIndex === targetAnchorIndex, edge.source.id === source.id, edge.target.id === target.id
            const hasLinked = edges.find(edge => {
                if (
                    (edge.get('source').get('id') === sourceNode.get('id') &&
                        edge.get('target').get('id') === e.target.cfg.nodeId &&
                        edge.get('sourceAnchorIndex') === this.sourceAnchorIndex &&
                        edge.get('targetAnchorIndex') === targetAnchorIndex) ||
                    (singleEdge && edge.get('target').get('id') === e.target.cfg.nodeId)
                ) {
                    return true;
                }
            });
            // 如果没有连线，则创建一条线
            if (!hasLinked) {
                this.graph.emit('before-edge-add', {
                    source: sourceNode,
                    target: node.getContainer().get('item'),
                    sourceAnchor: this.dragStartNode.anchorIndex,
                    targetAnchor: e.target.cfg.index
                });
            }
            
        }, // 节点拖拽
        _nodeOnDragStart(e, node) {
            const group = node.get('group');
            const currentShape = node.get('currentShape'); // rect-node
            const { radius } = node.get('originStyle');
            const { width, height, centerX, centerY } = node.getBBox();
            const { shapeType } = node.get('shapeFactory')[currentShape]; // rect
            // 构建样式属性
            let attrs = {
                fillOpacity: 0.1,
                fill: '#1890ff',
                stroke: '#1890ff',
                cursor: 'move',
                lineDash: [4, 4],
                width,
                height
            }
            switch(shapeType) {
                case 'circle':
                    this.distance = [e.x - centerX, e.y - centerY];
                    attrs = {
                        ...attrs,
                        x: 0,
                        y: 0,
                        r: width / 2
                    };
                    break;
                case 'rect':
                    this.distance = [e.x - centerX + width / 2, e.y - centerY + height / 2]; // 鼠标点击位置距离矩形左侧和下侧的距离
                    attrs = {
                        ...attrs,
                        x: -width / 2,
                        y: -height / 2,
                        r: width / 2
                    };
                    if (radius) attrs.radius = radius;
                    break;
                case 'path':
                    this.distance = [e.x - centerX, e.y - centerY];
                    attrs.path = node.get('keyShape').attrs.path;
                    attrs.size = [width, height];
                    attrs.x = 0;
                    attrs.y = 0;
                    break; 
            }
            // 绘制阴影图形
            const shadowNode = group.addShape(shapeType, {
                className: 'shadow-node',
                attrs
            });
            shadowNode.toFront();
        }, // 节点拖拽中
        _nodeOnDrag(e, node) {
            const group = node.get('group');
            const keyShape = group.getFirst();
            const currentShape = node.get('currentShape');
            const { shapeType } = node.get('shapeFactory')[currentShape];
            const { width, height, centerX, centerY } = node.getBBox();
            const shadowNode = group.getItem('shadow-node') || null;
            if (!shadowNode) {
                console.warn('暂不支持拖拽内置节点');
            }
            // 1. path
            if (shapeType === 'path') {
                const path = [['Z']];
                shadowNode.attr({ path });
            // 2. 其他图形
            } else {
                shadowNode.attr({
                    x: e.x - centerX -this.distance[0], // x轴移动距离
                    y: e.y - centerY - this.distance[1]
                })
            }
            shadowNode.toFront();
        }, // 节点拖拽完成，鼠标抬起
        _nodeOnDragEnd(e, node) {
            const group = node.get('group');
            const currentShape = node.get('currentShape'); // rect-node
            const shadowNode = group.getItem('shadow-node') || null;
            const { shapeType } = node.get('shapeFactory')[currentShape]; // rect
            const { width, height } = node.getBBox();

            // 移动图形的坐标
            const coords = {
                x: 0,
                y: 0
            };
            switch(shapeType) {
                case 'circle':
                    coords.x = e.x - this.distance[0];
                    coords.y = e.y - this.distance[1];
                    break;
                case 'rect':
                    coords.x = e.x - this.distance[0] + width / 2;
                    coords.y = e.y - this.distance[1] + height / 2;
                    break;
                case 'path':
                    coords.x = e.x - this.distance[0];
                    coords.y = e.y - this.distance[1];
                    break;
            }
            // 移除影子节点
            if (shadowNode) {
                shadowNode.remove();
            }
            // 添加移动动画，更新坐标
            node.updatePosition(coords);
            // 节点位置发生变化，刷新所有节点位置，并重新计算边的位置
            this.graph.refreshPositions();
        }
    })
}